
// let x = Object.create( null );
// x.hasOwnProperty( 'name' ); // TypeError: x.hasOwnProperty is not a function

let x = [];

console.log( x.length ); // 数组实例本身拥有一个 length 属性
// 当调用 x.hasOwnProperty 时:
// 1、首先寻找 x 所引用的实例本身上是否拥有 hasOwnProperty 函数，若有就调用
// 2、若x实例没有定义 hasOwnProperty 函数，则从 x.__proto__ 寻找该函数，若找到则调用
// 3、若 x.__proto__ 没有定义 hasOwnProperty 函数，则从 x.__proto__.__proto__ 寻找该函数，若找到则调用
// 4、否则继续沿着 原型链(prototype chain) 寻找，直到 Object.prototype 为止
// 5、若直到 Object.prototype 为止都未找到该函数，则抛出异常(TypeError)
console.log( x.hasOwnProperty( 'length' ) ); // true

console.log( '- - - - - - - - - - - - - - - - - - - - - - - -' );

function Animal( type ){
    this.type = type ; 
}

Animal.prototype.toString = function(){
    // console.log( this.type , this.name );
    return this.type + ":" + this.name ;
}

function Birds( name ){
    this.name = name ;
}

Birds.prototype = new Animal( '禽' );
Birds.prototype.constructor = Birds ;

function Beast( name ){
    this.name = name ;
}

Beast.prototype = new Animal( '兽' );
Beast.prototype.constructor = Beast ;

// 通过原型可以覆盖(重写)在父对象中的函数(父对象中的函数可能也是在其原型上定义的)
Beast.prototype.toString = function(){
    return '这是' + this.type + '类动物' + this.name ;
}

let b = new Birds( '布谷鸟' );
console.log( b.toString() ); // 沿着原型链寻找 toString 函数

let t = new Beast( '熊猫' );
console.log( t.toString() ); // 沿着原型链寻找 toString 函数

console.log( t.__proto__ === Beast.prototype ); // true
console.log( t.__proto__.__proto__ === Animal.prototype ); // true
console.log( t.__proto__.__proto__.__proto__ === Object.prototype ); // true

console.log( '- - - - - - - - - - - - - - - - - - - - - - - -' );

// ES 2015 ( ES 6 )

class Shape {
    constructor( name ) {
        this.name = name ;
    }
    toString(){
        return this.name ;
    }
}

class Triangle extends Shape {
    constructor( a , b , c ){
        super( '三角形' );
        this.first = a ;
        this.second = b ;
        this.third = c ;
    }
    toString(){
        return this.name + '(' + this.first + ',' + this.second + ',' + this.third +')';
    }
}

let s = new Triangle( 3 , 4 , 5 );
console.log( s );
console.log( s.toString() ); // 沿着原型链寻找 toString 函数